from coin.base.param_util import to_list
from coin.exchange.binance.kr_rest.product import BinanceProduct
from coin.exchange.bitmex.kr_rest.currency import BitmexCurrency
from coin.exchange.bitmex.kr_rest.futures_product import BitmexFuturesProduct
from coin.strategy.mm.subscription import SubscriptionRequest
import coin.support.pta.logic.pta_stats_calculator as psc

from coin.proto.coin_query_pb2 import (AccountBalance, CurrencyBalance)


def is_inverse(product):
  return psc.is_inverse_product(product)


def get_quote_currency(product):
  if is_inverse(product):
    if isinstance(product, BitmexFuturesProduct):
      quote_currency = BitmexCurrency.FromStr('BTC')
    else:
      quote_currency = product.base
  else:
    quote_currency = product.quote
  return quote_currency


def get_fee_coin_product(market_type, exchange, accounting_currency):
  accounting_currency = to_list(accounting_currency)
  fee_coin_product = []
  for currency in accounting_currency:
    currency_str = currency.currency
    if market_type == 'Spot':
      if exchange == 'Binance':
        symbol = 'BNB-%s' % currency_str
        fee_coin_product.append(BinanceProduct.FromStr(symbol))
  return fee_coin_product


def calculate_unrealized_pnl(product, pos, avg_price, ask0_price, bid0_price, *, inverse=True):
  if pos == 0:
    return 0
  mid_price = (ask0_price + bid0_price) / 2.
  if inverse:
    pnl = pos * (1. / avg_price - 1. / mid_price)
  else:
    pnl = pos * (mid_price - avg_price)
  return pnl


def reserve_as_proto(subreq, reserve_map):
  assert isinstance(subreq, SubscriptionRequest)
  assert isinstance(reserve_map, dict)
  each_balance = []
  for currency, reserve in reserve_map.items():
    each_balance.append(CurrencyBalance(currency=currency, total=reserve))
  return AccountBalance(exchange=subreq.exchange,
                        market_type=subreq.market_type,
                        each_balance=each_balance)
